Skip to content

Re-enable RootWeights proxy, scoped to set_root_weights - #3034

Closed
Rapiiidooo wants to merge 2 commits into
RaoFoundation:mainfrom
Rapiiidooo:feat/reenable-root-weights-proxy
Closed

Re-enable RootWeights proxy, scoped to set_root_weights#3034
Rapiiidooo wants to merge 2 commits into
RaoFoundation:mainfrom
Rapiiidooo:feat/reenable-root-weights-proxy

Conversation

@Rapiiidooo

@Rapiiidooo Rapiiidooo commented Aug 3, 2026

Copy link
Copy Markdown

What

Re-enables ProxyType::RootWeights with a deliberately minimal scope: a RootWeights proxy can dispatch SubtensorModule::set_root_weights and nothing else.

Why

The variant (SCALE index 12) was neutralized when proxy filters moved to deny-by-default allowlists: proxy.add_proxy(delegate, RootWeights, 0) still succeeds and the delegation shows up in Proxy.Proxies, but every subsequent proxy.proxy(...) is filtered. The grant looks placed yet does nothing — the worst of both worlds. With root reborn (#2968) making per-coldkey root weights meaningful again, delegating exactly that call to a low-value operational key (keeping the coldkey offline) is a real use case.

Changes

  • runtime/src/proxy_filters/call_groups.rs — new RootWeightCalls group containing only SubtensorModule::set_root_weights. It lives with the proxy-specific groups and overlaps SubtensorCommonCalls (the same way SmallTransferCalls overlaps BalanceTransferCalls) rather than granting that whole group: the validator's consensus-weight surface (set_weights, batch/commit/reveal) stays out of reach — that is precisely what this proxy type must not delegate.
  • runtime/src/proxy_filters/mod.rsRootWeights maps to RootWeightCalls in both the executable filter (proxy_type_filter) and the runtime-API metadata (proxy_filter_mode); both derive from the same group, so they cannot drift.
  • is_supersetNonTransfer ⊃ RootWeights already held. Added NonFungible ⊃ RootWeights: NonFungible already allows set_root_weights itself (via SubtensorCommonCalls), so it would be incoherent for a NonFungible proxy to be unable to manage a delegation that is a strict subset of its own rights. (is_superset gates a proxy adding/removing other delegations through proxy.proxy.)
  • common/src/proxy.rsRootWeights no longer reports is_deprecated(), so the runtime API's deprecated flag follows. Variant order is untouched: index 12 stays 12 and existing on-chain delegations keep their type.
  • SDK/docsadd_proxy / create_pure help text no longer lists RootWeights among the deny-all types; docs reference pages regenerated from the registries.

spec_version bumped 441 → 442: mainnet already runs 441 (root-reborn deployed), and the runtime-checks spec-version gate requires runtime-affecting PRs to carry a spec newer than mainnet unless labeled no-spec-version-bump (which is for changes deliberately shipping without a runtime release — not this one).

Existing on-chain grants

This change retroactively activates RootWeights delegations registered while the type was inert. Scan of Proxy.Proxies on finney at finalized block 8,765,950 (2026-08-03): 7,758 delegations across 6,722 delegator accounts — exactly one of type RootWeights:

delegator delegate delay
5HiFDVNX4ivCJFt9RvgRCtQKmAPgAXGX8BRgX3XKqfY9fFve 5FeNcqhfbLxkCeYtrKdDLkfNznmhCyvbAUMQNCfhddy8vHyX 0

Two options were weighed:

  1. Accept the existing grant (chosen). The right that activates is exactly what the type's name promises — add_proxy(RootWeights) had no other plausible intent — and the delegator can revoke at any time with remove_proxy. A one-shot purge migration to strip a single row adds more code and upgrade risk than the retroactive grant it would remove.
  2. Ship a storage migration purging pre-activation RootWeights entries. Rejected for the reason above; if reviewers prefer it, the affected entry is the single row listed here.

Additional mitigation: set_root_weights itself is still globally gated by RootWeightSettingEnabled (default off — it fails with RootWeightSettingDisabled until governance flips it via AdminUtils::sudo_set_root_weight_setting_enabled). The pre-existing delegation therefore cannot dispatch anything until that flag is enabled, leaving a clear window to revoke.

Tests

  • root_weights_grants_exactly_set_root_weights (new) — the filter accepts set_root_weights; rejects set_weights, add_stake, remove_stake, swap_hotkey, set_children; the metadata view exposes exactly one call.
  • narrow_proxies_have_exact_allow_lists — now pins allowed_calls(RootWeights) == {SubtensorModule::set_root_weights}.
  • non_fungible_superset_is_explicit_allowlist (new) — pins NonFungible's superset set to {NonFungible, RootWeights}, mirroring the existing NonTransfer pin.
  • any_allows_everything_and_deprecated_allow_nothing — RootWeights removed from the deny-all list (Triumvirate / Senate / Governance remain pinned there).
  • The pre-existing superset_relations_match_allowed_call_sets and all_call_groups_cover_runtime_call_metadata invariants cover the new superset edge and the group inventory (no duplicate in AllCalls).

Verification

  • SKIP_WASM_BUILD=1 cargo test -p node-subtensor-runtime -p subtensor-runtime-common — green (25 proxy tests, full crate suites).
  • cargo clippy (runtime + common, with tests) and cargo fmt — clean.
  • SDK: ruff, proxy pytest subset (34 passed), and the docs staleness check (generate.py --check) — green.

The RootWeights proxy type (index 12) was neutralized when proxy filters
moved to deny-by-default: add_proxy still accepted it but every proxied
call was filtered, so the grant looked placed while doing nothing. Root
reborn makes per-coldkey root weights meaningful again, so map the type
to a new RootWeightCalls group containing exactly
SubtensorModule::set_root_weights — deliberately not the
consensus-weight surface (set_weights, batch/commit/reveal) it shares
SubtensorCommonCalls with.

- allow NonFungible to manage the strictly-narrower RootWeights
  delegation in is_superset (it already allows set_root_weights via
  SubtensorCommonCalls); NonTransfer already could
- drop the deprecated flag; variant order and SCALE index unchanged
- update the SDK proxy help text and regenerate the docs pages

Mainnet has exactly one pre-existing RootWeights delegation (finney
block 8765950), which becomes effective with this change; shipping
without a purge migration — the grant matches the type's name and stays
revocable at any time via remove_proxy.
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

@Rapiiidooo is attempting to deploy a commit to the RaoFoundation Team on Vercel.

A member of the Team first needs to authorize it.

Mainnet already runs 441 (root-reborn deployed), and runtime-checks
requires runtime-affecting PRs to carry a spec_version newer than
mainnet unless deliberately shipping without a runtime release.
@Rapiiidooo

Rapiiidooo commented Aug 3, 2026

Copy link
Copy Markdown
Author

Closing this, the premise is obsolete.

RootWeights was designed back when set_root_weights was coldkey-signed (the hotkey was a call parameter), so delegating that coldkey signature made sense. Since root reborn the hotkey signs it directly (ensure_signed + root registration check), the coldkey is never involved anymore. Going through a coldkey proxy just fails with HotKeyNotRegisteredInSubNet.

So there's nothing left to delegate and nothing to protect either, the hotkey is already the hot key and can't move funds. Keeping the variant inert is fine. The one existing delegation on mainnet stays harmless.

@Rapiiidooo Rapiiidooo closed this Aug 3, 2026
@Rapiiidooo
Rapiiidooo deleted the feat/reenable-root-weights-proxy branch August 3, 2026 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant